package com.lfk.justweengine.Utils.tools;


import ohos.aafwk.ability.Ability;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Component;
import ohos.agp.components.ScrollView;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.render.*;
import ohos.agp.utils.*;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

/**
 * 图片处理工具类
 *
 * @author liufengkai
 */
public class PicUtils {



    /**
     * 将PixelMap转换成字符串
     *
     * @param pixelMap 传入图片的pixelMap
     * @return String
     */
    public static String bitmapToString(PixelMap pixelMap) {
        ByteArrayOutputStream bStream = new ByteArrayOutputStream();
        ImagePacker.PackingOptions opts = new ImagePacker.PackingOptions();
        opts.format = "image/jpeg";
        opts.quality = 100;
        ImagePacker imagePacker = ImagePacker.create();
        imagePacker.initializePacking(bStream, opts);
        imagePacker.addImage(pixelMap);
        imagePacker.finalizePacking();
        imagePacker.release();
        byte[] bytes = bStream.toByteArray();
        return Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 将字符串转换成PixelMap类型
     *
     * @param string 传入图片转出的字符串
     * @return PixelMap
     */
    public static PixelMap stringToBitmap(String string) {
        PixelMap bitmap = null;
        try {
            byte[] bitmapArray;
            bitmapArray = Base64.getDecoder().decode(string);
            ImageSource.SourceOptions sopts = new ImageSource.SourceOptions();
            ImageSource imageSource = ImageSource.create(bitmapArray, sopts);
            ImageSource.DecodingOptions dopts = new ImageSource.DecodingOptions();
            dopts.desiredPixelFormat = PixelFormat.ARGB_8888;
            bitmap = imageSource.createPixelmap(dopts);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * 截取整个屏幕
     *
     * @param context Ability
     * @return Bitmap
     */
    public PixelMap printAllScreen(Ability context) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        int w = display.getAttributes().width;
        int h = display.getAttributes().height;
        WindowManager windowManager = WindowManager.getInstance();
        Rect rect = new Rect(0, 0, w, h);
        return windowManager.captureScreen(rect, w, h, 0);
    }


    /**
     * 合成图层
     *
     * @param background 背景
     * @param foreground 前景
     * @return Bitmap
     */
    private PixelMap toConformBitmap(PixelMap background, PixelMap foreground) {
        if (background == null || foreground == null) {
            return null;
        }
        int bgWidth = background.getImageInfo().size.width;
        int bgHeight = background.getImageInfo().size.height;
        Texture texture = new Texture(bgWidth, bgHeight, Texture.ColorType.BGRA_8888_COLORTYPE, Texture.AlphaType.OPAQUE_ALPHATYPE);
        Canvas cv = new Canvas(texture);
        cv.drawPixelMapHolder(new PixelMapHolder(background), 0, 0, null);
        cv.drawPixelMapHolder(new PixelMapHolder(foreground), 0, 0, null);
        cv.save();
        cv.restore();
        return texture.getPixelMap();
    }

    /**
     * 将View转换为图片
     *
     * @param view 传入一个View
     * @return Bitmap
     */
    public static PixelMap getBitmapFromView(Component view) {
        PixelMap.InitializationOptions opts = new PixelMap.InitializationOptions();
        opts.pixelFormat = PixelFormat.ARGB_8888;
        opts.size = new Size(view.getWidth(), view.getHeight());
        PixelMap returnedBitmap = PixelMap.create(opts);
        Texture texture = new Texture(returnedBitmap);
        Canvas canvas = new Canvas(texture);
        Element element = view.getBackgroundElement();
        if (element != null) {
            element.drawToCanvas(canvas);
        } else {
            canvas.drawColor(0xFFFFFFFF, Canvas.PorterDuffMode.SCREEN);
        }
        return texture.getPixelMap();
    }

    /**
     * 自动压缩图片
     *
     * @param image 传入图片bitmap
     * @return bitmap
     */
    public static PixelMap compressImage(PixelMap image) {
        ByteArrayOutputStream baoS = new ByteArrayOutputStream();
        ImagePacker.PackingOptions opts = new ImagePacker.PackingOptions();
        opts.format = "image/jpeg";
        // 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baoS中
        opts.quality = 100;
        ImagePacker imagePacker = ImagePacker.create();
        imagePacker.initializePacking(baoS, opts);
        imagePacker.addImage(image);
        imagePacker.finalizePacking();
        imagePacker.release();
        // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
        while (baoS.toByteArray().length / 1024 > 100) {
            // 重置baoS即清空baoS
            baoS.reset();
            opts = new ImagePacker.PackingOptions();
            opts.format = "image/jpeg";
            // 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baoS中
            opts.quality -= 10;
            imagePacker = ImagePacker.create();
            imagePacker.initializePacking(baoS, opts);
            imagePacker.addImage(image);
            imagePacker.finalizePacking();
            imagePacker.release();
        }
        // 把压缩后的数据baos存放到ByteArrayInputStream中
        ByteArrayInputStream isBm = new ByteArrayInputStream(baoS.toByteArray());
        // 把ByteArrayInputStream数据生成图片
        ImageSource imageSource = ImageSource.create(isBm, null);
        ImageSource.DecodingOptions dopts = new ImageSource.DecodingOptions();
        dopts.desiredPixelFormat = PixelFormat.ARGB_8888;
        return imageSource.createPixelmap(dopts);
    }

    /**
     * 指定压缩的质量压缩图片
     *
     * @param image   传入图片的Bitmap
     * @param options 压缩图片质量
     * @return bitmap
     */
    public static PixelMap compressImage(PixelMap image, int options) {
        ByteArrayOutputStream baoS = new ByteArrayOutputStream();
        ImagePacker.PackingOptions opts = new ImagePacker.PackingOptions();
        opts.format = "image/jpeg";
        // 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baoS中
        opts.quality = options;
        ImagePacker imagePacker = ImagePacker.create();
        imagePacker.initializePacking(baoS, opts);
        imagePacker.addImage(image);
        imagePacker.finalizePacking();
        imagePacker.release();
        ByteArrayInputStream isBm = new ByteArrayInputStream(baoS.toByteArray());
        ImageSource imageSource = ImageSource.create(isBm, null);
        ImageSource.DecodingOptions dopts = new ImageSource.DecodingOptions();
        dopts.desiredPixelFormat = PixelFormat.ARGB_8888;
        return imageSource.createPixelmap(dopts);
    }

    /**
     * 按照比例进行缩放
     *
     * @param image  传入的Bitmap
     * @param width  传入的宽度
     * @param height 传入的高度
     * @return Bitmap
     */
    private static PixelMap compressWithMeasure(PixelMap image, int width, int height) {
        ByteArrayOutputStream baoS = new ByteArrayOutputStream();

        ImagePacker.PackingOptions opts = new ImagePacker.PackingOptions();
        opts.format = "image/jpeg";
        opts.quality = 100;
        ImagePacker imagePacker = ImagePacker.create();
        imagePacker.initializePacking(baoS, opts);
        imagePacker.addImage(image);
        imagePacker.finalizePacking();
        imagePacker.release();
        // 判断如果图片大于1M,进行压缩避免在生成图片（BitmapFactory.decodeStream）时溢出
        if (baoS.toByteArray().length / 1024 > 1024) {
            // 重置baoS即清空baoS
            baoS.reset();
            // 这里压缩50%，把压缩后的数据存放到baoS中
            opts = new ImagePacker.PackingOptions();
            opts.format = "image/jpeg";
            // 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baoS中
            opts.quality = 50;
            imagePacker = ImagePacker.create();
            imagePacker.initializePacking(baoS, opts);
            imagePacker.addImage(image);
            imagePacker.finalizePacking();
            imagePacker.release();
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baoS.toByteArray());

        ImageSource imageSource = ImageSource.create(isBm, new ImageSource.SourceOptions());
        ImageSource.DecodingOptions newOpts = new ImageSource.DecodingOptions();
        newOpts.desiredPixelFormat = PixelFormat.ARGB_8888;
        PixelMap bitmap = imageSource.createPixelmap(newOpts);

        int w = image.getImageInfo().size.width;
        int h = image.getImageInfo().size.height;
        // 缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        // be = 1表示不缩放
        int be = 1;
        if (w > h && w > width) {
            // 如果宽度大的话根据宽度固定大小缩放
            be = newOpts.desiredSize.width / width;
        } else if (w < h && h > height) {
            // 如果高度高的话根据宽度固定大小缩放
            be = newOpts.desiredSize.height / height;
        }
        if (be <= 0)
            be = 1;
        // 设置缩放比例
        newOpts.sampleSize = be;
        // 重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
        isBm = new ByteArrayInputStream(baoS.toByteArray());
        imageSource = ImageSource.create(isBm, new ImageSource.SourceOptions());
        bitmap = imageSource.createPixelmap(newOpts);
        // 压缩好比例大小后再进行质量压缩
        return compressImage(bitmap);
    }

    /**
     * 按照原比例进行缩放
     *
     * @param image PixelMap
     * @return Bitmap
     */
    public static PixelMap compressWithMeasure(PixelMap image) {
        return compressWithMeasure(image, image.getImageInfo().size.width, image.getImageInfo().size.height);
    }

    /**
     * 获取网络上的图片
     *
     * @param url String
     * @return PixelMap
     */
    public static PixelMap getHttpBitmap(String url) {
        URL myFileURL;
        PixelMap bitmap = null;
        try {
            myFileURL = new URL(url);

            // 获得连接
            HttpURLConnection conn = (HttpURLConnection) myFileURL.openConnection();

            conn.setConnectTimeout(6000);// 设置超时时间为6000毫秒，conn.setConnectionTiem(0);表示没有时间限制
            conn.setDoInput(true);// 连接设置获得数据流
            conn.setUseCaches(false);// 不使用缓存
            InputStream is = conn.getInputStream();// 得到数据流，这里会有调用conn.connect();

            // 解析得到图片
            ImageSource imageSource = ImageSource.create(is, new ImageSource.SourceOptions());
            ImageSource.DecodingOptions newOpts = new ImageSource.DecodingOptions();
            bitmap = imageSource.createPixelmap(newOpts);
            is.close();// 关闭数据流
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    /**
     * 从资源中获取Bitmap
     *
     * @param context Context
     * @param resid   例如这样：R.drawable.icon
     * @return PixelMap
     */
    public static PixelMap getBitmapFromResources(Context context, int resid) {
        InputStream inputStream = null;
        try {
            inputStream = context.getResourceManager().getResource(resid);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        }
        ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
        srcOpts.formatHint = "image/jpg";
        ImageSource imageSource = ImageSource.create(inputStream, srcOpts);
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        return imageSource.createPixelmap(decodingOptions);
    }

    /**
     * Bitmap转字节
     *
     * @param bitmap PixelMap
     * @return byte[]
     */
    public byte[] Bitmap2Bytes(PixelMap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImagePacker.PackingOptions opts = new ImagePacker.PackingOptions();
        opts.format = "image/jpeg";
        opts.quality = 100;
        ImagePacker imagePacker = ImagePacker.create();
        imagePacker.initializePacking(baos, opts);
        imagePacker.addImage(bitmap);
        imagePacker.finalizePacking();
        imagePacker.release();
        return baos.toByteArray();
    }

    /**
     * 字节转Bitmap
     *
     * @param bytes byte[]
     * @return PixelMap
     */
    public PixelMap Bytes2Bimap(byte[] bytes) {
        if (bytes.length != 0) {
            ImageSource.SourceOptions sopts = new ImageSource.SourceOptions();
            ImageSource imageSource = ImageSource.create(bytes, sopts);
            ImageSource.DecodingOptions dopts = new ImageSource.DecodingOptions();
            return imageSource.createPixelmap(dopts);
        } else {
            return null;
        }
    }

    /**
     * Bitmap缩放，可能比例要注意一下
     *
     * @param bitmap PixelMap
     * @param width 宽
     * @param height 高
     * @return PixelMap
     */
    public static PixelMap zoomBitmap(PixelMap bitmap, int width, int height) {
        int w = bitmap.getImageInfo().size.width;
        int h = bitmap.getImageInfo().size.height;
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size(width, height);
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        return PixelMap.create(bitmap, new ohos.media.image.common.Rect(0, 0, w, h), initializationOptions);
    }

    /**
     * 将Drawable转化为Bitmap
     *
     * @param drawable Element
     * @return PixelMap
     */
    public static PixelMap drawable2Bitmap(Element drawable) {
        // 取 drawable 的长宽
        int w = drawable.getWidth();
        int h = drawable.getHeight();

        // 取 drawable 的颜色格式
        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = drawable.getAlpha() != Element.ALPHA_MIN ? PixelFormat.ARGB_8888 : PixelFormat.RGB_565;
        options.size = new Size(w, h);
        // 建立对应 bitmap
        PixelMap bitmap = PixelMap.create(options);

        // 建立对应 bitmap 的画布
        Canvas canvas = new Canvas(new Texture(bitmap));
        drawable.setBounds(0, 0, w, h);

        // 把 drawable 内容画到画布中
        drawable.drawToCanvas(canvas);
        return bitmap;
    }

    /**
     * Bitmap转换成Drawable
     *
     * @param bitmap PixelMap
     * @return Element
     */
    public static Element Bitmap2Drawable(PixelMap bitmap) {
        return new PixelMapElement(bitmap);
    }

    /**
     * 获得圆角图片
     *
     * @param bitmap PixelMap
     * @param roundPx float
     * @return PixelMap
     */
    public static PixelMap getRoundedCornerBitmap(PixelMap bitmap, float roundPx) {

        int w = bitmap.getImageInfo().size.width;
        int h = bitmap.getImageInfo().size.height;
        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = PixelFormat.ARGB_8888;
        options.size = new Size(w, h);
        PixelMap output = PixelMap.create(options);
        Canvas canvas = new Canvas(new Texture(output));
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, w, h);
        final RectFloat rectF = new RectFloat(rect);
        paint.setAntiAlias(true);
        canvas.drawColor(Color.argb(0, 0, 0, 0), Canvas.PorterDuffMode.CLEAR);
        paint.setColor(new Color(color));
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setBlendMode(BlendMode.SRC_IN);
        PixelMapHolder pixelMapHolder = new PixelMapHolder(bitmap);
        canvas.drawPixelMapHolderRect(pixelMapHolder, rectF, paint);
        return output;
    }

    /**
     * 获得带倒影的图片
     *
     * @param bitmap PixelMap
     * @return PixelMap
     */
    public static PixelMap createReflectionImageWithOrigin(PixelMap bitmap) {
        final int reflectionGap = 4;
        int w = bitmap.getImageInfo().size.width;
        int h = bitmap.getImageInfo().size.height;

        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);

        PixelMap reflectionImage;
        ohos.media.image.common.Rect rect = new ohos.media.image.common.Rect(0, h / 2, w, h / 2);
        reflectionImage = PixelMap.create(bitmap, rect, new PixelMap.InitializationOptions());
        PixelMap.InitializationOptions opts = new PixelMap.InitializationOptions();
        opts.pixelFormat = PixelFormat.ARGB_8888;
        opts.size = new Size(w, (h + h / 2));
        PixelMap bitmapWithReflection = PixelMap.create(opts);
        Canvas canvas = new Canvas(new Texture(bitmapWithReflection));
        canvas.drawPixelMapHolder(new PixelMapHolder(bitmap), 0, 0, new Paint());

        canvas.drawPixelMapHolder(new PixelMapHolder(reflectionImage), 0, h + reflectionGap, new Paint());

        Paint paint = new Paint();
        Point[] newPoints = {new Point(0, bitmap.getImageInfo().size.height)};
        float[] newStops = {0, bitmapWithReflection.getImageInfo().size.height + reflectionGap};
        Color[] newColors = {new Color(0x70ffffff), new Color(0x00ffffff)};
        LinearShader shader = new LinearShader(newPoints, newStops, newColors, Shader.TileMode.CLAMP_TILEMODE);
        paint.setShader(shader, Paint.ShaderType.GROUP_SHADER);
        // Set the Transfer mode to be porter duff and destination in
        paint.setBlendMode(BlendMode.SRC_IN);
        // Draw a rectangle using the paint with our linear gradient
        canvas.drawRect(0, h, w, bitmapWithReflection.getImageInfo().size.height + reflectionGap, paint);

        return bitmapWithReflection;
    }

    public static class ImagePiece {
        public PixelMap bitmap;
        public int index;

        public ImagePiece(PixelMap bitmap) {
            this.bitmap = bitmap;
            this.index = 0;
        }

        public ImagePiece(PixelMap bitmap, int index) {
            this.bitmap = bitmap;
            this.index = index;
        }
    }

    /**
     * 截图分片
     *
     * @param context Context
     * @param bitmap PixelMap
     * @return List<ImagePiece>
     */
    public static List<ImagePiece> spilt(Context context, PixelMap bitmap) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        int screenHeight = display.getAttributes().height;
        List<ImagePiece> list = new ArrayList<>();
        if (bitmap.getImageInfo().size.height <= screenHeight) {
            list.add(new ImagePiece(bitmap));
            return list;
        }
        int pageNum = Math.round(bitmap.getImageInfo().size.height * 1.0f / screenHeight);
        for (int i = 0; i < pageNum; i++) {
            int xValue = 0;
            int yValue = i * screenHeight + (int) AttrHelper.getDensity(context) * 16;
            PixelMap.InitializationOptions opts = new PixelMap.InitializationOptions();
            opts.pixelFormat = PixelFormat.ARGB_8888;
            list.add(new ImagePiece(
                    PixelMap.create(bitmap, new ohos.media.image.common.Rect(xValue, yValue, bitmap.getImageInfo().size.width, screenHeight), opts),
                    i));
        }
        return list;
    }

    /**
     * 截取ScrollView
     * @param context Context
     * @param v ScrollView
     * @return PixelMap
     */
    public static PixelMap createBitmap(Context context, ScrollView v) {
        int width = 0, height = 0;
        for (int i = 0; i < v.getChildCount(); i++) {
            width += v.getComponentAt(i).getWidth();
            height += v.getComponentAt(i).getHeight();
        }
        if (width <= 0 || height <= 0) {
            return null;
        }
        int h = context.getAbilityInfo().getDefaultFormHeight();
        if (height < h)
            height = h;
        PixelMap.InitializationOptions opts = new PixelMap.InitializationOptions();
        opts.pixelFormat = PixelFormat.ARGB_8888;
        opts.size = new Size(width, height);
        PixelMap bitmap = PixelMap.create(opts);
        RectFloat rect = new RectFloat(new Rect(0,0,width,height));
        v.addDrawTask(new Component.DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                PixelMapHolder pixelMapHolder = new PixelMapHolder(bitmap);
                canvas.drawPixelMapHolderRect(pixelMapHolder, rect, new Paint());
            }
        });
        return bitmap;
    }

    /**
     * 制作圆形图片
     *
     * @param rect PixelMap
     */
    public static PixelMap rectBitmapToCircle(PixelMap rect) {
        Shader mBitmapShader = new PixelMapShader(new PixelMapHolder(rect), Shader.TileMode.CLAMP_TILEMODE, Shader.TileMode.CLAMP_TILEMODE);
        Paint paint = new Paint();
        paint.setShader(mBitmapShader, Paint.ShaderType.PIXELMAP_SHADER);
        PixelMap.InitializationOptions opts = new PixelMap.InitializationOptions();
        opts.pixelFormat = PixelFormat.ARGB_8888;
        opts.size = new Size(rect.getImageInfo().size.width, rect.getImageInfo().size.height);
        PixelMap output = PixelMap.create(opts);
        Canvas canvas = new Canvas(new Texture(output));
        canvas.drawCircle(rect.getImageInfo().size.width / 2,
                rect.getImageInfo().size.height / 2,
                Math.min(rect.getImageInfo().size.width, rect.getImageInfo().size.height) / 2
                , paint);
        return output;
    }

    public static PixelMap getMaskBitmap(int w, int h) {
        PixelMap.InitializationOptions opts = new PixelMap.InitializationOptions();
        opts.pixelFormat = PixelFormat.ARGB_8888;
        opts.size = new Size(w, h);
        PixelMap bitmap = PixelMap.create(opts);
        Canvas canvas = new Canvas(new Texture(bitmap));
        canvas.drawColor(Color.BLACK.getValue(), Canvas.PorterDuffMode.CLEAR);
        return bitmap;
    }
}
